package org.openapitools.server.api;

import java.io.IOException;
import java.io.File;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

import io.helidon.common.GenericType;
import io.helidon.http.media.multipart.MultiPart;
import io.helidon.http.media.multipart.ReadablePart;
import io.helidon.webserver.http.ServerRequest;

@io.helidon.common.Generated(value = "org.openapitools.codegen.languages.JavaHelidonServerCodegen",
                             trigger = "utility",
                             version = "stable")
class PartsUtils {

    private final Map<String, ReadablePart> parts = new LinkedHashMap<>();

    static Map<String, ReadablePart> partsMap(ServerRequest request) {
        Map<String, ReadablePart> parts = new LinkedHashMap<>();
        request.content().as(MultiPart.class).forEachRemaining(part -> parts.put(part.name(), part));
        return parts;
    }

    static PartsUtils create(ServerRequest request) {
        return new PartsUtils(request);
    }

    private PartsUtils(ServerRequest request) {
        request.content().as(MultiPart.class).forEachRemaining(part -> parts.put(part.name(), part));
    }

    <T> T part(String partName, Class<T> type, T defaultValue) {
        ReadablePart part = parts.get(partName);
        if (part == null) {
            return defaultValue;
        }
        return part.as(type);
    }

    <T> Optional<T> partOpt(String partName, Class<T> type, T defaultValue) {
        return Optional.ofNullable(part(partName, type, defaultValue));
    }

    <T> T part(String partName, GenericType<T> type, T defaultValue) {
        ReadablePart part = parts.get(partName);
        if (part == null) {
            return defaultValue;
        }
        return part.as(type);
    }

    <T> Optional<T> partOpt(String partName, GenericType<T> type, T defaultValue) {
        return Optional.ofNullable(part(partName, type, defaultValue));
    }

    InputStream inputStreamPart(String partName) {
        ReadablePart part = parts.get(partName);
        if (part == null) {
            return null;
        }
        return part.inputStream();
    }

    Optional<InputStream> inputStreamPartOpt(String partName) {
        return Optional.ofNullable(inputStreamPart(partName));
    }

    File filePart(String partName, Path directory) {
        ReadablePart part = parts.get(partName);
        if (part == null) {
            return null;
        }
        try (InputStream inputStream = part.inputStream()) {
            Path path = directory.resolve(part.fileName().orElse(partName));
            inputStream.transferTo(Files.newOutputStream(path, StandardOpenOption.CREATE_NEW));
            return path.toFile();
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }
}
